﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace CQRS.Infrastructure
{
    /// <summary>
    /// Ties entities such as commands and events to their handlers.
    /// </summary>
    internal class HandlerHelper
    {
        public static IDictionary<Type, IList<Type>> GetEntityHandlers(Assembly assembly, Type messageHandlerType)
        {
            IDictionary<Type, IList<Type>> handlersDictionary = new Dictionary<Type, IList<Type>>();
            List<Type> handlers = assembly.GetTypes()
                .Where(x =>
                       x.GetInterfaces().Any(y => y.IsGenericType && y.GetGenericTypeDefinition() == messageHandlerType))
                .ToList();

            foreach (Type handler in handlers)
            {
                Type entity = handler.GetInterfaces()
                    .First(x => x.IsGenericType && x.GetGenericTypeDefinition() == messageHandlerType)
                    .GetGenericArguments().First();

                if (!handlersDictionary.ContainsKey(entity))
                    handlersDictionary.Add(entity, new List<Type>());

                handlersDictionary[entity].Add(handler);
            }

            return handlersDictionary;
        }

        public static IEnumerable<Type> GetEntities(Assembly assembly, Type messageType)
        {
            return assembly
                .GetTypes()
                .Where(x => x.BaseType == messageType)
                .ToList();
        }
    }
}